1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package sun.security.jgss.krb5;
27
28 import org.ietf.jgss.*;
29 import sun.security.jgss.*;
30 import java.io.InputStream;
31 import java.io.OutputStream;
32 import java.io.IOException;
33 import java.io.ByteArrayOutputStream;
34 import sun.security.krb5.Confounder;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 class WrapToken extends MessageToken {
50
51
52
53 static final int CONFOUNDER_SIZE = 8;
54
55
56
57
58
59
60
61
62 static final byte[][] pads = {
63 null,
64 {0x01},
65 {0x02, 0x02},
66 {0x03, 0x03, 0x03},
67 {0x04, 0x04, 0x04, 0x04},
68 {0x05, 0x05, 0x05, 0x05, 0x05},
69 {0x06, 0x06, 0x06, 0x06, 0x06, 0x06},
70 {0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07},
71 {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}
72 };
73
74
75
76
77
78
79
80
81 private boolean readTokenFromInputStream = true;
82 private InputStream is = null;
83 private byte[] tokenBytes = null;
84 private int tokenOffset = 0;
85 private int tokenLen = 0;
86
87
88
89
90
91
92
93
94 private byte[] dataBytes = null;
95 private int dataOffset = 0;
96 private int dataLen = 0;
97
98
99 private int dataSize = 0;
100
101
102 byte[] confounder = null;
103 byte[] padding = null;
104
105 private boolean privacy = false;
106
107
108
109
110
111
112
113
114
115
116
117
118
119 public WrapToken(Krb5Context context,
120 byte[] tokenBytes, int tokenOffset, int tokenLen,
121 MessageProp prop) throws GSSException {
122
123
124 super(Krb5Token.WRAP_ID, context,
125 tokenBytes, tokenOffset, tokenLen, prop);
126
127 this.readTokenFromInputStream = false;
128
129
130 this.tokenBytes = tokenBytes;
131 this.tokenOffset = tokenOffset;
132 this.tokenLen = tokenLen;
133 this.privacy = prop.getPrivacy();
134 dataSize =
135 getGSSHeader().getMechTokenLength() - getKrb5TokenSize();
136 }
137
138
139
140
141
142
143
144
145
146
147
148
149 public WrapToken(Krb5Context context,
150 InputStream is, MessageProp prop)
151 throws GSSException {
152
153
154 super(Krb5Token.WRAP_ID, context, is, prop);
155
156
157 this.is = is;
158 this.privacy = prop.getPrivacy();
159
160
161
162
163
164
165
166 dataSize =
167 getGSSHeader().getMechTokenLength() - getTokenSize();
168
169
170 }
171
172
173
174
175
176
177
178
179 public byte[] getData() throws GSSException {
180
181 byte[] temp = new byte[dataSize];
182 getData(temp, 0);
183
184
185 byte[] retVal = new byte[dataSize - confounder.length -
186 padding.length];
187 System.arraycopy(temp, 0, retVal, 0, retVal.length);
188
189 return retVal;
190 }
191
192
193
194
195
196
197
198
199
200
201
202
203 public int getData(byte[] dataBuf, int dataBufOffset)
204 throws GSSException {
205
206 if (readTokenFromInputStream)
207 getDataFromStream(dataBuf, dataBufOffset);
208 else
209 getDataFromBuffer(dataBuf, dataBufOffset);
210
211 return (dataSize - confounder.length - padding.length);
212 }
213
214
215
216
217
218
219
220
221
222
223
224 private void getDataFromBuffer(byte[] dataBuf, int dataBufOffset)
225 throws GSSException {
226
227 GSSHeader gssHeader = getGSSHeader();
228 int dataPos = tokenOffset +
229 gssHeader.getLength() + getTokenSize();
230
231 if (dataPos + dataSize > tokenOffset + tokenLen)
232 throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
233 "Insufficient data in "
234 + getTokenName(getTokenId()));
235
236
237
238
239 confounder = new byte[CONFOUNDER_SIZE];
240
241
242
243 if (privacy) {
244 cipherHelper.decryptData(this,
245 tokenBytes, dataPos, dataSize, dataBuf, dataBufOffset);
246
247
248
249
250
251
252
253
254
255 } else {
256
257
258
259 System.arraycopy(tokenBytes, dataPos,
260 confounder, 0, CONFOUNDER_SIZE);
261 int padSize = tokenBytes[dataPos + dataSize - 1];
262 if (padSize < 0)
263 padSize = 0;
264 if (padSize > 8)
265 padSize %= 8;
266
267 padding = pads[padSize];
268
269
270 System.arraycopy(tokenBytes, dataPos + CONFOUNDER_SIZE,
271 dataBuf, dataBufOffset, dataSize -
272 CONFOUNDER_SIZE - padSize);
273
274
275
276
277
278 }
279
280
281
282
283
284 if (!verifySignAndSeqNumber(confounder,
285 dataBuf, dataBufOffset,
286 dataSize - CONFOUNDER_SIZE
287 - padding.length,
288 padding))
289 throw new GSSException(GSSException.BAD_MIC, -1,
290 "Corrupt checksum or sequence number in Wrap token");
291 }
292
293
294
295
296
297
298
299
300
301
302
303 private void getDataFromStream(byte[] dataBuf, int dataBufOffset)
304 throws GSSException {
305
306 GSSHeader gssHeader = getGSSHeader();
307
308
309
310
311
312
313 confounder = new byte[CONFOUNDER_SIZE];
314
315 try {
316
317
318
319 if (privacy) {
320 cipherHelper.decryptData(this, is, dataSize,
321 dataBuf, dataBufOffset);
322
323
324
325
326
327
328
329
330 } else {
331
332
333
334 readFully(is, confounder);
335
336 if (cipherHelper.isArcFour()) {
337 padding = pads[1];
338 readFully(is, dataBuf, dataBufOffset, dataSize-CONFOUNDER_SIZE-1);
339 } else {
340
341
342 int numBlocks = (dataSize - CONFOUNDER_SIZE)/8 - 1;
343 int offset = dataBufOffset;
344 for (int i = 0; i < numBlocks; i++) {
345 readFully(is, dataBuf, offset, 8);
346 offset += 8;
347 }
348
349 byte[] finalBlock = new byte[8];
350 readFully(is, finalBlock);
351
352 int padSize = finalBlock[7];
353 padding = pads[padSize];
354
355
356 System.arraycopy(finalBlock, 0, dataBuf, offset,
357 finalBlock.length - padSize);
358 }
359 }
360 } catch (IOException e) {
361 throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
362 getTokenName(getTokenId())
363 + ": " + e.getMessage());
364 }
365
366
367
368
369
370 if (!verifySignAndSeqNumber(confounder,
371 dataBuf, dataBufOffset,
372 dataSize - CONFOUNDER_SIZE
373 - padding.length,
374 padding))
375 throw new GSSException(GSSException.BAD_MIC, -1,
376 "Corrupt checksum or sequence number in Wrap token");
377 }
378
379
380
381
382
383
384
385
386
387 private byte[] getPadding(int len) {
388 int padSize = 0;
389
390
391 if (cipherHelper.isArcFour()) {
392 padSize = 1;
393 } else {
394 padSize = len % 8;
395 padSize = 8 - padSize;
396 }
397 return pads[padSize];
398 }
399
400 public WrapToken(Krb5Context context, MessageProp prop,
401 byte[] dataBytes, int dataOffset, int dataLen)
402 throws GSSException {
403
404 super(Krb5Token.WRAP_ID, context);
405
406 confounder = Confounder.bytes(CONFOUNDER_SIZE);
407
408 padding = getPadding(dataLen);
409 dataSize = confounder.length + dataLen + padding.length;
410 this.dataBytes = dataBytes;
411 this.dataOffset = dataOffset;
412 this.dataLen = dataLen;
413
414
415
416
417
418
419
420
421
422 genSignAndSeqNumber(prop,
423 confounder,
424 dataBytes, dataOffset, dataLen,
425 padding);
426
427
428
429
430
431
432
433 if (!context.getConfState())
434 prop.setPrivacy(false);
435
436 privacy = prop.getPrivacy();
437 }
438
439 public void encode(OutputStream os) throws IOException, GSSException {
440
441 super.encode(os);
442
443
444 if (!privacy) {
445
446
447 os.write(confounder);
448
449
450 os.write(dataBytes, dataOffset, dataLen);
451
452
453 os.write(padding);
454
455 } else {
456
457 cipherHelper.encryptData(this, confounder,
458 dataBytes, dataOffset, dataLen, padding, os);
459 }
460
461 }
462
463 public byte[] encode() throws IOException, GSSException {
464
465 ByteArrayOutputStream bos = new ByteArrayOutputStream(dataSize + 50);
466 encode(bos);
467 return bos.toByteArray();
468 }
469
470 public int encode(byte[] outToken, int offset)
471 throws IOException, GSSException {
472
473
474 ByteArrayOutputStream bos = new ByteArrayOutputStream();
475 super.encode(bos);
476 byte[] header = bos.toByteArray();
477 System.arraycopy(header, 0, outToken, offset, header.length);
478 offset += header.length;
479
480
481 if (!privacy) {
482
483
484 System.arraycopy(confounder, 0, outToken, offset,
485 confounder.length);
486 offset += confounder.length;
487
488
489 System.arraycopy(dataBytes, dataOffset, outToken, offset,
490 dataLen);
491 offset += dataLen;
492
493
494 System.arraycopy(padding, 0, outToken, offset, padding.length);
495
496 } else {
497
498 cipherHelper.encryptData(this, confounder, dataBytes,
499 dataOffset, dataLen, padding, outToken, offset);
500
501
502 }
503
504
505
506
507 return (header.length + confounder.length + dataLen + padding.length);
508
509 }
510
511 protected int getKrb5TokenSize() throws GSSException {
512 return (getTokenSize() + dataSize);
513 }
514
515 protected int getSealAlg(boolean conf, int qop) throws GSSException {
516 if (!conf) {
517 return SEAL_ALG_NONE;
518 }
519
520
521 return cipherHelper.getSealAlg();
522 }
523
524
525
526 static int getSizeLimit(int qop, boolean confReq, int maxTokenSize,
527 CipherHelper ch) throws GSSException {
528 return (GSSHeader.getMaxMechTokenSize(OID, maxTokenSize) -
529 (getTokenSize(ch) + CONFOUNDER_SIZE) - 8);
530 }
531
532 }